package com.guapi.mapper;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.guapi.annotation.TimeFlag;
import com.guapi.annotation.UniqueIndex;
import com.guapi.exception.SelfException;
import com.guapi.mapper.wrapper.SelfQueryWrapper;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 需要研究下怎么获取父类里的扩展字段
 *
 * @param <T>
 */
public interface SelfBaseMapper<T> extends BaseMapper<T> {

    @Override
    int insert(T entity);

    @Override
    int deleteById(Serializable id);

    @Override
    int deleteById(T entity);

    @Override
    default boolean exists(Wrapper<T> queryWrapper) {
        return BaseMapper.super.exists(queryWrapper);
    }

    default T select(T entity) {
        return selectOne(new SelfQueryWrapper<>(entity));
    }

    @Override
    T selectById(Serializable id);

    default List<T> selectList(T entity) {
        return selectList(new SelfQueryWrapper<>(entity));
    }

    /**
     * 传入参数的任意内容都将被匹配
     *
     * @param entity
     * @return
     */
    default List<T> selectConditions(T entity) {
        String regex = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$";
        Pattern date = Pattern.compile(regex);
        SelfQueryWrapper<T> wrapper = new SelfQueryWrapper<T>();
        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
                // 跳过静态字段和常量字段
                continue;
            }
            try {
                field.setAccessible(true);
                TableField annotation = field.getAnnotation(TableField.class);
                if (annotation != null) {
                    if (!annotation.exist()) {
                        continue;
                    }
                    if (annotation.value() != null && field.get(entity) != null) {
                        wrapper.eq(annotation.value(), field.get(entity));
                    }
                } else {
                    if (field.get(entity) != null) {
                        if (field.getAnnotation(TimeFlag.class) != null) {
                            if (date.matcher((String) field.get(entity)).matches()) {
                                //输入时间以后
                                wrapper.gt(field.getName(), field.get(entity));
                            }
                        } else {
                            wrapper.eq(field.getName(), field.get(entity));
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                throw new SelfException("不能传入空对象,请检查输入对象", e);
            }
        }
        wrapper.or();
        return selectList(wrapper);
    }

    /**
     * 可根据主键或唯一索引更新对象
     * 若无唯一索引则插入对象
     * 如果更新为空值，会被判断跳过，原因在于MybatisPlus，使用‘NULL’以取代插入空
     *
     * @param entity
     * @return
     */
    default boolean saveOrUpdate(T entity) {
        Field[] fields = entity.getClass().getDeclaredFields();
        Map<String, Object> uniqueFields = new HashMap<>();
        Map<String, Object> changeDataMap = new HashMap<>();

        boolean isUnique = false;
        int isSuccess = 0;
        try {
            Field idField = entity.getClass().getSuperclass().getDeclaredField("id");
            idField.setAccessible(true);
            for (Field field : fields) {
                field.setAccessible(true);
                TableField annotation = field.getAnnotation(TableField.class);
                if (annotation != null) {
                    if (!annotation.exist()) {
                        continue;
                    }
                }
                if (field.getAnnotation(UniqueIndex.class) != null && field.get(entity) != null) {
                    isUnique = true;
                    if (annotation != null && annotation.value() != null) {
                        uniqueFields.put(annotation.value(), field.get(entity));
                    } else {
                        uniqueFields.put(field.getName(), field.get(entity));
                    }
                }
                if (field.get(entity) != null) {
                    changeDataMap.put(field.getName(), field.get(entity));
                } else {
                    changeDataMap.put(field.getName(), null);
                }
            }
            //存在唯一索引且唯一索引的字段存在值
            if (isUnique && !uniqueFields.values().isEmpty() && idField.get(entity) == null) {
                List<T> uniqueEntity = selectByMap(uniqueFields);
                if (uniqueEntity.size() >= 2) {
                    throw new SelfException("500", "出现未知错误，唯一索引集：" + uniqueFields.keySet() + "存在重复，请检查数据库！");
                }
                if (uniqueEntity.size() == 0) {
                    //有唯一索引的插入逻辑
                    isSuccess = insert(entity);
                } else {
                    //唯一索引的修改逻辑
                    T databaseEntity = uniqueEntity.get(0);
                    changeDataMap.forEach((key, value) -> {
                        try {
                            Field field = databaseEntity.getClass().getDeclaredField(key);
                            field.setAccessible(true);
                            if (field.get(databaseEntity) != value) {
                                field.set(databaseEntity, value);
                            }
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    });
                    isSuccess = updateById(databaseEntity);
                }
            } else if (idField.get(entity) != null) {
                //存在主键，则通过主键更新
                isSuccess = updateById(entity);
            } else {
                isSuccess = insert(entity);
            }
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
            throw new SelfException("更新或插入存在异常");
        }
        return isSuccess == 1;
    }

    default T deleteEntity(T entity) {
        return delete(new SelfQueryWrapper<>(entity)) == 1 ? entity : null;
    }

    /**
     * 模糊查询
     *
     * @param entity
     * @return
     */
    default List<T> selectFuzzy(T entity) {
        SelfQueryWrapper<T> wrapper = new SelfQueryWrapper<>();
        Field[] fields = entity.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                TableField annotation = field.getAnnotation(TableField.class);

                if (annotation != null) {
                    if (!annotation.exist()) {
                        continue;
                    }
                    if (annotation.value() != null && field.get(entity) != null) {
                        wrapper.like(annotation.value(), field.get(entity));
                    }
                } else {
                    if (field.get(entity) != null) {
                        wrapper.like(field.getName(), field.get(entity));
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new SelfException("不能传入空对象,请检查输入对象", e);
        }
        return selectList(wrapper);
    }


    default List<T> getByExpired(T entity) {
        SelfQueryWrapper<T> wrapper = new SelfQueryWrapper<>();
        Field[] fields = entity.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                TimeFlag annotation = field.getAnnotation(TimeFlag.class);
                if (annotation == null || field.get(entity) == null) {
                    continue;
                } else {
                    // TableField valueKey = field.getAnnotation(TableField.class);
                    // if (valueKey==null||valueKey.value()==null){
                    //     continue;
                    // }else {
                    // }
                    wrapper.le(field.getName(), field.get(entity));
                    wrapper.gt(field.getName(), DateUtil.now());
                }
            }
            return selectList(wrapper);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new SelfException("没能获取到对象的值");
        }
    }
}
